package cn.gayaguoguo.guohealthindicator.manager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

import cn.gayaguoguo.guohealthindicator.GuoHealthIndicator;
import cn.gayaguoguo.guohealthindicator.util.RoundingUtil;

public class HealthBarManager {
	
	private GuoHealthIndicator plugin;
	
	private HashMap<String, LivingEntity> linkMap = new HashMap<>();
	
	private HashMap<String, BossBar> barMap = new HashMap<>();
	
	private HashMap<String, Integer> taskMap = new HashMap<>();
	
	private List<BossBar> barList = new ArrayList<>();
	
	public HealthBarManager(GuoHealthIndicator plugin){
		this.plugin = plugin;
	}
	
	public synchronized void addLink(String playerName, LivingEntity livingEntity){
		if (taskMap.containsKey(playerName)){
			Bukkit.getScheduler().cancelTask(taskMap.get(playerName));
		}
		linkMap.put(playerName, livingEntity);
		clearBar(playerName);
		showBar(playerName);
		BukkitRunnable bukkitRunnable = new BukkitRunnable() {
			
			@Override
			public void run() {

				delLink(playerName);
				
			}
		};
		taskMap.put(playerName, bukkitRunnable.runTaskLater(plugin, plugin.getConfigManager().duration).getTaskId());
	}
	
	public synchronized void delLink(String playerName){
		if (!linkMap.containsKey(playerName)){
			return;
		}
		linkMap.remove(playerName);
		clearBar(playerName);
	}
	
	@SuppressWarnings("deprecation")
	public synchronized void showBar(String playerName){
		Player player = Bukkit.getPlayer(playerName);
		if (player == null){
			return;
		}
		LivingEntity livingEntity = linkMap.get(playerName);
		if (livingEntity == null){
			return;
		}
		
		String title = plugin.getConfigManager().title;
		
		Double health = livingEntity.getHealth();
		Double maxHealth = livingEntity.getMaxHealth();
		
		Double progress = health / maxHealth;
		
		String mobName = getName(livingEntity);
		BarColor barColor = getBarColor(livingEntity);
		BarStyle barStyle = getBarStyle(livingEntity);
		
		title = title.replace("%name%", mobName);
		title = title.replace("%health%", RoundingUtil.format(health));
		title = title.replace("%maxHealth%", RoundingUtil.format(maxHealth));
		
		BossBar bossBar = Bukkit.createBossBar(title, barColor, barStyle);
		bossBar.setProgress(progress);
		
		bossBar.addPlayer(player);
		barMap.put(playerName, bossBar);
		barList.add(bossBar);
		
		if (health == 0D) {
			new BukkitRunnable() {
				
				@Override
				public void run() {
					
					delLink(playerName);
					
				}
			}.runTaskLater(plugin, 20);
		}
	}
	
	public synchronized void clearBar(String playerName){
		if (barMap.containsKey(playerName)){
			barMap.get(playerName).removeAll();
			barMap.remove(playerName);
		}
	}
	
	public synchronized void showAllBar(){
		for (String playerName : linkMap.keySet()){
			showBar(playerName);
		}
	}
	
	public synchronized void clearAllBar(){
		for (BossBar bossBar : barMap.values()){
			bossBar.removeAll();
		}
		barMap.clear();
	}
	
	public synchronized void deleteAllBar() {
		for (BossBar bossBar : barList) {
			bossBar.removeAll();
		}
		barList.clear();
	}
	
	private String getName(LivingEntity livingEntity){
		if (livingEntity instanceof Player){
			return livingEntity.getName();
		}else {
			String name = livingEntity.getCustomName();
			if (name == null){
				name = plugin.getConfigManager().config.getString("mobs." + livingEntity.getType().name() + ".name");
			}
			if (name == null){
				name = livingEntity.getType().name();
			}
			return name;
		}
	}
	
	private BarColor getBarColor(LivingEntity livingEntity){
		try {
			return Enum.valueOf(BarColor.class, plugin.getConfigManager().config.getString("mobs." + livingEntity.getType().name() + ".barColor"));
		} catch (Exception e) {
			try {
				return Enum.valueOf(BarColor.class, plugin.getConfigManager().config.getString("setting.barColor"));
			} catch (Exception e2) {
				return BarColor.RED;
			}
		}
	}
	
	private BarStyle getBarStyle(LivingEntity livingEntity){
		try {
			return Enum.valueOf(BarStyle.class, plugin.getConfigManager().config.getString("mobs." + livingEntity.getType().name() + ".barStyle"));
		} catch (Exception e) {
			try {
				return Enum.valueOf(BarStyle.class, plugin.getConfigManager().config.getString("setting.barStyle"));
			} catch (Exception e2) {
				return BarStyle.SEGMENTED_20;
			}
		}
	}
}
